package com.example.lib_xinlian;

import static android.content.ContentValues.TAG;

import android.util.Log;

import com.bean.ReaderParams;
import com.sum.common.bean.ReadMode;
import com.sum.common.bean.ReaderExt;
import com.sum.common.bean.Stats;
import com.sum.common.bean.TagInfo;
import com.sum.common.bean.WriteParams;
import com.sum.common.inter.IUHFManager;
import com.sum.common.inter.OnInventoryListener;
import com.sum.common.panling.PowerUtils;
import com.sum.common.utils.ConvertUtils;
import com.sum.common.utils.SortUtils;
import com.uhf.api.cls.ErrInfo;
import com.uhf.api.cls.Reader;
import com.uhf.api.cls.Reader.AntPower;
import com.uhf.api.cls.Reader.AntPowerConf;
import com.uhf.api.cls.Reader.CustomParam_ST;
import com.uhf.api.cls.Reader.EmbededData_ST;
import com.uhf.api.cls.Reader.HoptableData_ST;
import com.uhf.api.cls.Reader.Inv_Potl;
import com.uhf.api.cls.Reader.Inv_Potls_ST;
import com.uhf.api.cls.Reader.Mtr_Param;
import com.uhf.api.cls.Reader.READER_ERR;
import com.uhf.api.cls.Reader.Region_Conf;
import com.uhf.api.cls.Reader.SL_TagProtocol;
import com.uhf.api.cls.Reader.TAGINFO;
import com.uhf.api.cls.Reader.TagFilter_ST;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class XinlianUHFManager implements IUHFManager {
    private static final int ANT_COUNT = 1;

    private final Reader mReader;
    private final ReaderParams mReaderParams;
    private volatile boolean isRunning;
    private volatile boolean isConnect;
    private static volatile XinlianUHFManager mInstance;
    private OnInventoryListener tagListener;
    private String deviceModel;
    private int maxSerialNumber;
    private int totalCount;
    private final List<TagInfo> tagList; //获取标签数据
    private int tagCountPerSecond;
    private final ExecutorService executor;
    String[] spipower = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11",
            "12", "13", "14", "15", "16", "17", "18", "19",
            "20", "21", "22", "23", "24", "25", "26", "27",
            "28", "29", "30", "31", "32", "33"};
    int minpw = Integer.valueOf(spipower[0]);

    private XinlianUHFManager() {
        this.mReader = new Reader();
        this.mReaderParams = new ReaderParams();
        this.tagList = Collections.synchronizedList(new ArrayList<>());
        this.executor = Executors.newSingleThreadExecutor();
    }

    @Override
    public IUHFManager getInstance() {
        if (mInstance == null) {
            synchronized (XinlianUHFManager.class) {
                if (mInstance == null) {
                    mInstance = new XinlianUHFManager();
                }
            }
        }
        return mInstance;
    }

    // 基础连接方法
    @Override
    public boolean connect(String port, int baudRate) {
        if (isConnect) {
            return true;
        }
        Reader.READER_ERR result = mReader.InitReader_Notype(port, ANT_COUNT);
        if (result == READER_ERR.MT_OK_ERR) {
            getDeviceModel();
            setFastMode();
            isConnect = true;
        }
        return isConnect;
    }

    @Override
    public boolean isConnected() {
        return isConnect;
    }

    @Override
    public String getHardware() {
        return "";
    }

    @Override
    public ReaderExt.READER_ERR getLastDetailError(ReaderExt.ErrInfo info) {
        ErrInfo err = new ErrInfo();
        READER_ERR code = mReader.GetLastDetailError(err);
        if (code == READER_ERR.MT_OK_ERR) {
            info.errstr = err.errstr;
            info.derrcode = err.derrcode;
        }
        return ReaderExt.READER_ERR.valueOf(code.value());
    }

    // 实现清理方法
    @Override
    public void clearTagList() {
        tagCountPerSecond = 0;
        if(!tagList.isEmpty()){
            tagList.clear();
        }
        maxSerialNumber=0;
        totalCount=0;
    }

    @Override
    public void setOnInventoryListener(OnInventoryListener listener) {
        this.tagListener = listener;
    }

    // 转换工具方法
    private ReaderExt.READER_ERR convertError(READER_ERR result) {
        return result == READER_ERR.MT_OK_ERR ? ReaderExt.READER_ERR.MT_OK_ERR : ReaderExt.READER_ERR.valueOf(result.value());
    }

    @Override
    public boolean close() {
        try {
            isConnect = false;
            if (executor != null && !executor.isShutdown()) {
                executor.shutdown();
                try {
                    if (!executor.awaitTermination(1000, TimeUnit.MILLISECONDS)) {
                        executor.shutdownNow();
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    executor.shutdownNow();
                }
            }
            mReader.CloseReader();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    // 工具方法，用于处理标签结果
    private void processTagInfo(TAGINFO taginfo, boolean isFastMode) {
        String epcId = ConvertUtils.bytes2HexString(taginfo.EpcId,false);
        int count = taginfo.ReadCnt;
        int rssi = taginfo.RSSI;
        String tid = isFastMode ? "" : ConvertUtils.bytes2HexString(taginfo.EmbededData,false);

        synchronized (tagList) {
            // 查找已存在的标签
            int findIndex = -1;
            for(int i =0;i<tagList.size();i++){
                if (tagList.get(i).getEpc().equals(epcId)) {
                    findIndex = i;
                    break;
                }
            }

            if (findIndex != -1) {
                TagInfo tagInfo= tagList.get(findIndex);
                // 更新已存在的标签
                tagInfo.setCount(tagInfo.getCount() + count);
                tagInfo.setRssi(rssi);
                tagInfo.setTid(tid);
                tagList.remove(findIndex);
                tagList.add(tagInfo);
            } else {
                // 添加新标签
                TagInfo newTag = new TagInfo();
                newTag.setEpc(epcId);
                newTag.setCount(count);
                newTag.setRssi(rssi);
                newTag.setTid(tid);
                newTag.setSerialNumber(tagList.size()+1);
                tagList.add(newTag);
            }
            //最大排列序号(标签个数)
            maxSerialNumber = tagList.size();
            //读取到标签总数
            totalCount = 0;

            for (int i = 1; i < tagList.size(); i++) {
                TagInfo item = tagList.get(i);
                totalCount += item.getCount();
            }
            //获取每秒所读张数
            tagCountPerSecond += count;

            //添加代码排序
            Collections.sort(tagList, (t1, t2) ->
                    Integer.compare(t1.getSerialNumber(), t2.getSerialNumber()));
        }
    }

    @Override
    public ReaderExt.READER_ERR asyncStartReading(ReadMode readMode) {
        if (isRunning) {
            return ReaderExt.READER_ERR.MT_OTHER_ERR;
        }
        isRunning = true;

        try {
            // 根据模式设置相应参数
            switch (readMode) {
                case NORMAL:
                    setupNormalMode();
                    break;
                case FAST:
                    setFastMode();
                    break;
                case GROUP_TID:
                    setupGroupTidMode();
                    break;
            }

            // 启动异步读取线程
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    while (isRunning) {
                        try {
                            switch (readMode) {
                                case NORMAL:
                                    processNormalReading();
                                    break;
                                case FAST:
                                    processFastReading();
                                    break;
                                case GROUP_TID:
                                    processGroupTidReading();
                                    break;
                            }
                        } catch (Exception e) {
                            if (tagListener != null) {
                                tagListener.onError(ReaderExt.READER_ERR.MT_OTHER_ERR);
                            }
                        }
                    }
                }
            });

            return ReaderExt.READER_ERR.MT_OK_ERR;
        } catch (Exception e) {
            return ReaderExt.READER_ERR.MT_OTHER_ERR;
        }
    }

    private void processNormalReading() {
        int[] tagCount = new int[1];
        READER_ERR result = mReader.TagInventory_Raw(
                mReaderParams.uants,
                mReaderParams.uants.length,
                (short) mReaderParams.readtime,
                tagCount
        );

        if (result == READER_ERR.MT_OK_ERR && tagCount[0] > 0) {
            processTagResults(tagCount[0], false);
        }
    }

    private void processFastReading() {
        int[] tagCount = new int[1];
        READER_ERR result = mReader.AsyncStartReading(
                mReaderParams.uants,
                mReaderParams.uants.length,
                mReaderParams.option
        );

        if (mReader.AsyncGetTagCount(tagCount) == READER_ERR.MT_OK_ERR && tagCount[0] > 0) {
            processTagResults(tagCount[0], true);
        }
    }

    private void processGroupTidReading() {
        processNormalReading(); // TID分组模式使用普通读取方式
    }

    private void processTagResults(int tagCount, boolean isFastMode) {
        for (int i = 0; i < tagCount; i++) {
            TAGINFO taginfo = mReader.new TAGINFO();
            READER_ERR er = isFastMode ?
                    mReader.AsyncGetNextTag(taginfo) :
                    mReader.GetNextTag(taginfo);

            if (er == READER_ERR.MT_OK_ERR) {
                processTagInfo(taginfo, isFastMode);
            }
        }

        // 通知监听器
        if (tagListener != null) {
            List<TagInfo> copyList;
            synchronized (tagList) {
                copyList = new ArrayList<>(tagList);
            }
            tagListener.onInventoryListener(copyList,new Stats(tagCountPerSecond,maxSerialNumber,totalCount));
        }
    }

    @Override
    public List<TagInfo> tagInventoryRealTime() {
        int[] tagCount = new int[1];
        READER_ERR result = mReader.TagInventory_Raw(
                mReaderParams.uants,
                mReaderParams.uants.length,
                (short) mReaderParams.readtime,
                tagCount
        );

        if (result == READER_ERR.MT_OK_ERR && tagCount[0] > 0) {
            List<TagInfo> tagList = new ArrayList<>();
            for (int i = 0; i < tagCount[0]; i++) {
                TAGINFO tagInfo = mReader.new TAGINFO();
                if (mReader.GetNextTag(tagInfo) == READER_ERR.MT_OK_ERR) {
                    TagInfo tag = new TagInfo();
                    tag.setEpc(ConvertUtils.bytes2HexString(tagInfo.EpcId,false));
                    tag.setCount(tagInfo.ReadCnt);
                    tag.setRssi(tagInfo.RSSI);
                    tagList.add(tag);
                }
            }
            return tagList;
        }
        return null;
    }

    @Override
    public ReaderExt.READER_ERR asyncStopReading() {
        isRunning = false;
        READER_ERR result = mReader.AsyncStopReading();
        return convertError(result);
    }

    @Override
    public boolean stopTagInventory() {
        return mReader.StopReading() == READER_ERR.MT_OK_ERR;
    }

    @Override
    public List<TagInfo> tagInventoryByTimer(short readtime) {
        int[] tagCount = new int[1];
        READER_ERR result = mReader.TagInventory_Raw(
                mReaderParams.uants,
                mReaderParams.uants.length,
                readtime,
                tagCount
        );

        if (result == READER_ERR.MT_OK_ERR && tagCount[0] > 0) {
            List<TagInfo> tagList = new ArrayList<>();
            for (int i = 0; i < tagCount[0]; i++) {
                TAGINFO tagInfo = mReader.new TAGINFO();
                if (mReader.GetNextTag(tagInfo) == READER_ERR.MT_OK_ERR) {
                    TagInfo tag = new TagInfo();
                    tag.setEpc(ConvertUtils.bytes2HexString(tagInfo.EpcId,false));
                    tag.setCount(tagInfo.ReadCnt);
                    tag.setRssi(tagInfo.RSSI);
                    tag.setTid(ConvertUtils.bytes2HexString(tagInfo.EmbededData,false));
                    tagList.add(tag);
                }
            }
            return tagList;
        }
        return  null;
    }

    private void setupNormalMode() {
        // 默认设置,不需要特殊配置
    }

    private void setupGroupTidMode() {
        // 配置嵌入式数据读取参数
        EmbededData_ST embeddedData = mReader.new EmbededData_ST();
        embeddedData.startaddr = 0;
        embeddedData.bank = 2;
        embeddedData.bytecnt = 12;
        embeddedData.accesspwd = null;

        mReader.ParamSet(Mtr_Param.MTR_PARAM_TAG_EMBEDEDDATA, embeddedData);
    }

    private void getDeviceModel() {
        try {
            Reader.HardwareDetails hardwareDetails = mReader.new HardwareDetails();
            Reader.READER_ERR err = mReader.GetHardwareDetails(hardwareDetails);
            if (err == Reader.READER_ERR.MT_OK_ERR) {
                this.deviceModel = hardwareDetails.module.toString();
                Log.d("XinlianUHFManager", "设备型号：" + deviceModel);
            } else {
                Log.e("XinlianUHFManager", "获取设备型号失败：" + err);
                deviceModel = "unknown";
            }
        } catch (Exception e) {
            Log.e("XinlianUHFManager", "获取型号异常：" + e.getMessage());
            deviceModel = "unknown";
        }
    }
    @Override
    public ReaderExt.READER_ERR setFastMode() {
        CustomParam_ST customParam = mReader.new CustomParam_ST();
        if("MODOULE_SIM3100".equals(deviceModel)){
            customParam.ParamName = "Reader/usermode";
            customParam.ParamVal = new byte[1];
            customParam.ParamVal[0] = Byte.parseByte(String.valueOf(81));
            Log.d(TAG, "cpara: "+ customParam.ParamVal[0]);
        }
        else {
        customParam.ParamName = "Reader/Ex10fastmode";
        byte[] paramVal = new byte[22];
        paramVal[0] = 1;
        paramVal[1] = 20;
        for (int i = 0; i < 20; i++) {
            paramVal[i + 2] = (byte) i;
        }
        customParam.ParamVal = paramVal;
        }
        READER_ERR result = mReader.ParamSet(Mtr_Param.MTR_PARAM_CUSTOM, customParam);
        Log.d(TAG, "setFastMode: "+result);
        if (result == READER_ERR.MT_OK_ERR) {
            result = mReader.ParamSet(Mtr_Param.MTR_PARAM_TAG_EMBEDEDDATA, null);

            if (result == READER_ERR.MT_OK_ERR) {
                int metaFlag = 0x0002;
                mReaderParams.option = (metaFlag << 8) | 10;
            }
        }
        return convertError(result);
    }

    @Override
    public void setSingleLabelMode(boolean enabled) {
        mReader.ParamSet(Mtr_Param.MTR_PARAM_POTL_GEN2_SESSION,
                new int[]{enabled ? 0 : 1});
        mReader.ParamSet(Mtr_Param.MTR_PARAM_POTL_GEN2_TAGENCODING,
                new int[]{enabled ? 113 : 111});
        mReader.ParamSet(Mtr_Param.MTR_PARAM_POTL_GEN2_Q,
                new int[]{-1});
    }

    @Override
    public void setGroupTidMode(boolean enabled) {
        if(enabled){
            mReader.ParamSet(Mtr_Param.MTR_PARAM_POTL_GEN2_SESSION, new int[]{1});
            mReader.ParamSet(Mtr_Param.MTR_PARAM_POTL_GEN2_TAGENCODING, new int[]{107});
            mReader.ParamSet(Mtr_Param.MTR_PARAM_POTL_GEN2_TARGET, new int[]{2});
            mReader.ParamSet(Mtr_Param.MTR_PARAM_POTL_GEN2_Q, new int[]{-1});
        }else {
            mReader.ParamSet(Mtr_Param.MTR_PARAM_POTL_GEN2_SESSION, new int[]{1});
            mReader.ParamSet(Mtr_Param.MTR_PARAM_POTL_GEN2_TAGENCODING, new int[]{111});
            mReader.ParamSet(Mtr_Param.MTR_PARAM_POTL_GEN2_TARGET, new int[]{2});
            mReader.ParamSet(Mtr_Param.MTR_PARAM_POTL_GEN2_Q, new int[]{-1});
        }
    }
    @Override
    public boolean setInventoryFilter(byte[] fdata, int fbank, int fstartaddr, boolean matching) {
        TagFilter_ST filterMask = mReader.new TagFilter_ST();
        filterMask.bank = fbank;
        filterMask.startaddr = fstartaddr;
        return mReader.ParamSet(Mtr_Param.MTR_PARAM_TAG_FILTER, filterMask) == READER_ERR.MT_OK_ERR;
    }

    @Override
    public boolean setCancleInventoryFilter() {
        return mReader.ParamSet(Mtr_Param.MTR_PARAM_TAG_FILTER, null) == READER_ERR.MT_OK_ERR;
    }

    @Override
    public ReaderExt.READER_ERR getTagData(int region, int startaddr, int len,
                                           byte[] rdata, byte[] password, short timeout) {
        READER_ERR result = mReader.GetTagData(
                mReaderParams.opant,
                (char) region,
                startaddr,
                len,
                rdata,
                password,
                (short) mReaderParams.optime
        );
        return convertError(result);
    }

    @Override
    public byte[] getTagDataByFilter(int mbank, int startaddr, int len,
                                     byte[] password, short timeout, byte[] fdata,
                                     int fbank, int fstartaddr, boolean matching) {
        try {
            if (!setInventoryFilter(fdata, fbank, fstartaddr, matching)) {
                return null;
            }

            byte[] rdata = new byte[len * 2];
            ReaderExt.READER_ERR result = getTagData(mbank, startaddr, len, rdata, password, timeout);

            return result == ReaderExt.READER_ERR.MT_OK_ERR ? rdata : null;
        } finally {
            setCancleInventoryFilter();
        }
    }

    @Override
    public ReaderExt.READER_ERR writeTagData(WriteParams writeParams, int regoin, int startaddress, String oldData,
                                             byte[] data, int datalen, byte[] accesspasswd, short timeout) {
        READER_ERR result = mReader.WriteTagData(
                mReaderParams.opant,
                (char) regoin,
                startaddress,
                data,
                datalen,
                accesspasswd,
                (short) mReaderParams.optime
        );
        return convertError(result);
    }

    @Override
    public ReaderExt.READER_ERR writeTagDataByFilter(char mbank, int startaddress,
                                                     byte[] data, int datalen, byte[] accesspasswd, short timeout,
                                                     byte[] fdata, int fbank, int fstartaddr, boolean matching) {
        try {
            if (!setInventoryFilter(fdata, fbank, fstartaddr, matching)) {
                return ReaderExt.READER_ERR.MT_OTHER_ERR;
            }
            return writeTagData(null,mbank, startaddress, null,data, datalen, accesspasswd, timeout);
        } finally {
            setCancleInventoryFilter();
        }
    }

    @Override
    public ReaderExt.READER_ERR writeTagEPC(byte[] data, byte[] accesspwd, short timeout) {
        READER_ERR result = mReader.WriteTagData(
                mReaderParams.opant,
                '1',
                2,
                data,
                data.length,
                accesspwd,
                timeout
        );
        return convertError(result);
    }

    @Override
    public ReaderExt.READER_ERR writeTagEPCByFilter(byte[] data, byte[] accesspwd,
                                                    short timeout, byte[] fdata, int fbank, int fstartaddr, boolean matching) {
        try {
            if (!setInventoryFilter(fdata, fbank, fstartaddr, matching)) {
                return ReaderExt.READER_ERR.MT_OTHER_ERR;
            }
            return writeTagEPC(data, accesspwd, timeout);
        } finally {
            setCancleInventoryFilter();
        }
    }

    @Override
    public ReaderExt.READER_ERR lockTag(ReaderExt.Lock_Obj lockobject,
                                        ReaderExt.Lock_Type locktype, byte[] accesspasswd, int timeout) {
        READER_ERR result = mReader.LockTag(
                mReaderParams.opant,
                (byte) lockobject.value(),
                (short) locktype.value(),
                accesspasswd,
                (short) mReaderParams.optime
        );
        return convertError(result);
    }

    @Override
    public ReaderExt.READER_ERR lockTagByFilter(ReaderExt.Lock_Obj lockobject,
                                                ReaderExt.Lock_Type locktype, byte[] accesspasswd, short timeout,
                                                byte[] fdata, int fbank, int fstartaddr, boolean matching) {
        try {
            if (!setInventoryFilter(fdata, fbank, fstartaddr, matching)) {
                return ReaderExt.READER_ERR.MT_OTHER_ERR;
            }
            return lockTag(lockobject, locktype, accesspasswd, timeout);
        } finally {
            setCancleInventoryFilter();
        }
    }

    @Override
    public ReaderExt.READER_ERR killTag(byte[] killpasswd, int timeout) {
        READER_ERR result = mReader.KillTag(
                mReaderParams.opant,
                killpasswd,
                (short) mReaderParams.optime
        );
        return convertError(result);
    }

    @Override
    public ReaderExt.READER_ERR killTagByFilter(byte[] killpasswd, int timeout,
                                                byte[] fdata, int fbank, int fstartaddr, boolean matching) {
        try {
            if (!setInventoryFilter(fdata, fbank, fstartaddr, matching)) {
                return ReaderExt.READER_ERR.MT_OTHER_ERR;
            }
            return killTag(killpasswd, timeout);
        } finally {
            setCancleInventoryFilter();
        }
    }

    @Override
    public ReaderExt.READER_ERR setRegion(int region) {
        int band = region;
        Region_Conf rre;
        switch (band) {
            case 0:
                rre = Region_Conf.RG_PRC;
                break;
            case 1:
                rre = Region_Conf.RG_PRC2;
                break;
            case 2:
                rre = Region_Conf.RG_NONE;
                break;
            case 3:
                rre = Region_Conf.RG_NA;
                break;
            case 4:
                rre = Region_Conf.RG_EU3;
                break;
            default:
                rre = Region_Conf.RG_NONE;
                break;
        }
        READER_ERR result = mReader.ParamSet(
                Mtr_Param.MTR_PARAM_FREQUENCY_REGION,
                rre
        );
        if (result == READER_ERR.MT_OK_ERR) {
            handleRegionSet();
        }
        return convertError(result);
    }

    private void handleRegionSet() {
        HoptableData_ST hdst = mReader.new HoptableData_ST();
        READER_ERR result = mReader.ParamGet(
                Mtr_Param.MTR_PARAM_FREQUENCY_HOPTABLE,
                hdst
        );

        if (result == READER_ERR.MT_OK_ERR) {
            SortUtils.Sort(hdst.htb, hdst.lenhtb);
        }
    }

    @Override
    public ReaderExt.Region_Conf getRegion() {
        Region_Conf[] rcf = new Region_Conf[1];
        READER_ERR result = mReader.ParamGet(
                Mtr_Param.MTR_PARAM_FREQUENCY_REGION,
                rcf
        );
        return result == READER_ERR.MT_OK_ERR ?
                ReaderExt.Region_Conf.valueOf(rcf[0].value()) : null;
    }

    @Override
    public int[] getFrequencyPoints() {
        HoptableData_ST hdst = mReader.new HoptableData_ST();
        READER_ERR result = mReader.ParamGet(
                Mtr_Param.MTR_PARAM_FREQUENCY_HOPTABLE,
                hdst
        );
        return result == READER_ERR.MT_OK_ERR ? hdst.htb : null;
    }

    @Override
    public ReaderExt.READER_ERR setFrequencyPoints(int[] frequencyPoints) {
        HoptableData_ST hdst = mReader.new HoptableData_ST();
        hdst.lenhtb = frequencyPoints.length;
        hdst.htb = frequencyPoints;

        READER_ERR result = mReader.ParamSet(
                Mtr_Param.MTR_PARAM_FREQUENCY_HOPTABLE,
                hdst
        );
        return convertError(result);
    }

    @Override
    public String getSession() {
        int[] sessionValue = new int[]{-1};
        READER_ERR sessionResult = mReader.ParamGet(
                Mtr_Param.MTR_PARAM_POTL_GEN2_SESSION,
                sessionValue
        );
        return sessionResult == READER_ERR.MT_OK_ERR ? "S1" : "";
    }

    @Override
    public String getFlag() {
        int[] flagValue = new int[]{-1};
        READER_ERR flagResult = mReader.ParamGet(
                Mtr_Param.MTR_PARAM_POTL_GEN2_TARGET,
                flagValue
        );
        return flagResult == READER_ERR.MT_OK_ERR ? "A-B" : "";
    }

    // 未实现的方法
    @Override
    public boolean setInventoryParameter(Map<String, Object> params) {
        return false;
    }

    @Override
    public String getInventoryParameter() {
        return "";
    }

    @Override
    public int getTemperature() {
        int[] temp = new int[1];
        mReader.ParamGet(Mtr_Param.MTR_PARAM_RF_TEMPERATURE, temp);
        return temp[0];
    }

    @Override
    public ReaderExt.READER_ERR setPower(int power) {
        int[] powers = new int[16];

        Arrays.fill(powers, power);
        AntPowerConf powerConf = mReader.new AntPowerConf();
        powerConf.antcnt = ANT_COUNT;
        powerConf.Powers = new AntPower[ANT_COUNT];
        for (int i = 0; i < ANT_COUNT; i++) {
            AntPower antPower = mReader.new AntPower();
            antPower.antid = i + 1;
            antPower.readPower = (short) (minpw + 100 * powers[i]);
            antPower.writePower = (short) (minpw + 100 * powers[i]);
            powerConf.Powers[i] = antPower;
        }

        READER_ERR result = mReader.ParamSet(
                Mtr_Param.MTR_PARAM_RF_ANTPOWER,
                powerConf
        );
        if (result == READER_ERR.MT_OK_ERR) {
            updatePowerParams(powerConf);
        }
        return convertError(result);
    }

    @Override
    public int[] getPower() {
        AntPowerConf apcf2 = mReader.new AntPowerConf();
        READER_ERR result = mReader.ParamGet(
                Mtr_Param.MTR_PARAM_RF_ANTPOWER,
                apcf2
        );
        if (result == READER_ERR.MT_OK_ERR) {
            int readPower = apcf2.Powers[0].readPower;
            int writePower = apcf2.Powers[0].writePower;
            for (int i = 0; i < apcf2.antcnt; i++) {
                if (i == 0) {
                    readPower = ((apcf2.Powers[i].readPower - minpw) / 100);
                    writePower = ((apcf2.Powers[i].writePower - minpw) / 100);
                } else if (i == 1) {
                    readPower =  ((apcf2.Powers[i].readPower - minpw) / 100);
                    writePower =((apcf2.Powers[i].writePower - minpw) / 100);
                } else if (i == 2) {
                    readPower =((apcf2.Powers[i].readPower - minpw) / 100);
                    writePower =((apcf2.Powers[i].writePower - minpw) / 100);
                } else if (i == 3) {
                    readPower =((apcf2.Powers[i].readPower - minpw) / 100);
                    writePower =((apcf2.Powers[i].writePower - minpw) / 100);
                } else if (i == 4) {
                    readPower =((apcf2.Powers[i].readPower - minpw) / 100);
                    writePower =((apcf2.Powers[i].writePower - minpw) / 100);
                } else if (i == 5) {
                    readPower =((apcf2.Powers[i].readPower - minpw) / 100);
                    writePower =((apcf2.Powers[i].writePower - minpw) / 100);
                } else if (i == 6) {
                    readPower =((apcf2.Powers[i].readPower - minpw) / 100);
                    writePower =((apcf2.Powers[i].writePower - minpw) / 100);
                } else if (i == 7) {
                    readPower =((apcf2.Powers[i].readPower - minpw) / 100);
                    writePower =((apcf2.Powers[i].writePower - minpw) / 100);
                } else if (i == 8) {
                    readPower =((apcf2.Powers[i].readPower - minpw) / 100);
                    writePower =((apcf2.Powers[i].writePower - minpw) / 100);
                } else if (i == 9) {
                    readPower =((apcf2.Powers[i].readPower - minpw) / 100);
                    writePower =((apcf2.Powers[i].writePower - minpw) / 100);
                } else if (i == 10) {
                    readPower =((apcf2.Powers[i].readPower - minpw) / 100);
                    writePower =((apcf2.Powers[i].writePower - minpw) / 100);
                } else if (i == 11) {
                    readPower =((apcf2.Powers[i].readPower - minpw) / 100);
                    writePower =((apcf2.Powers[i].writePower - minpw) / 100);
                } else if (i == 12) {
                    readPower =((apcf2.Powers[i].readPower - minpw) / 100);
                    writePower =((apcf2.Powers[i].writePower - minpw) / 100);
                } else if (i == 13) {
                    readPower =((apcf2.Powers[i].readPower - minpw) / 100);
                    writePower =((apcf2.Powers[i].writePower - minpw) / 100);
                } else if (i == 14) {
                    readPower =((apcf2.Powers[i].readPower - minpw) / 100);
                    writePower =((apcf2.Powers[i].writePower - minpw) / 100);
                } else if (i == 15) {
                    readPower =((apcf2.Powers[i].readPower - minpw) / 100);
                    writePower =((apcf2.Powers[i].writePower - minpw) / 100);
                }

                return new int[]{readPower, writePower};
            }
        }
        return null;
    }

    private void updatePowerParams(AntPowerConf powerConf) {
        int[] rpow = new int[powerConf.antcnt];
        int[] wpow = new int[powerConf.antcnt];
        for (int i = 0; i < powerConf.antcnt; i++) {
            rpow[i] = powerConf.Powers[i].readPower;
            wpow[i] = powerConf.Powers[i].writePower;
        }
        mReaderParams.rpow = rpow;
        mReaderParams.wpow = wpow;
    }

    @Override
    public int getProtocol() {
        Inv_Potls_ST protocolST = mReader.new Inv_Potls_ST();
        if (mReader.ParamGet(Mtr_Param.MTR_PARAM_TAG_INVPOTL, protocolST) == READER_ERR.MT_OK_ERR) {
            return protocolST.potls[0].potl.value();
        }
        return -1;
    }

    @Override
    public ReaderExt.READER_ERR setProtocol(String protocol) {
        List<SL_TagProtocol> protocols = getProtocolsForSelection(protocol);
        Inv_Potls_ST protocolST = createProtocolConfig(protocols);
        READER_ERR result = mReader.ParamSet(
                Mtr_Param.MTR_PARAM_TAG_INVPOTL,
                protocolST
        );

        if (result == READER_ERR.MT_OK_ERR) {
            List<String> protocolNames = new ArrayList<>();
            for (SL_TagProtocol p : protocols) {
                protocolNames.add(p.name());
            }
            updateProtocolParams(protocolNames);
        }
        return convertError(result);
    }

    @Override
    public int getQValue() {
        int[] value = new int[]{-1};
        READER_ERR result = mReader.ParamGet(
                Mtr_Param.MTR_PARAM_POTL_GEN2_Q,
                value
        );
        if (result == READER_ERR.MT_OK_ERR) {
            return value[0] == 255 ? -1 : value[0];
        }
        return -1;
    }

    @Override
    public ReaderExt.READER_ERR setQValue(int selectedPosition) {
        int[] value = new int[]{selectedPosition - 1};
        READER_ERR result = mReader.ParamSet(
                Mtr_Param.MTR_PARAM_POTL_GEN2_Q,
                value
        );

        if (result == READER_ERR.MT_OK_ERR) {
            mReaderParams.qv = value[0];
        }
        return convertError(result);
    }

    // 辅助方法
    private Inv_Potls_ST createProtocolConfig(List<SL_TagProtocol> protocols) {
        Inv_Potls_ST protocolST = mReader.new Inv_Potls_ST();
        protocolST.potlcnt = protocols.size();
        Inv_Potl[] potls = new Inv_Potl[protocols.size()];

        for (int i = 0; i < protocols.size(); i++) {
            Inv_Potl potl = mReader.new Inv_Potl();
            potl.weight = 30;
            potl.potl = protocols.get(i);
            potls[i] = potl;
        }

        protocolST.potls = potls;
        return protocolST;
    }

    private void updateProtocolParams(List<String> protocolNames) {
        mReaderParams.invpro.clear();
        mReaderParams.invpro.addAll(protocolNames);
    }

    private List<SL_TagProtocol> getProtocolsForSelection(String selectedProtocol) {
        SL_TagProtocol protocol;
        switch (selectedProtocol) {
            case "Gen2":
                protocol = SL_TagProtocol.SL_TAG_PROTOCOL_GEN2;
                break;
            case "6B":
                protocol = SL_TagProtocol.SL_TAG_PROTOCOL_ISO180006B;
                break;
            case "IPX64":
                protocol = SL_TagProtocol.SL_TAG_PROTOCOL_IPX64;
                break;
            case "IPX256":
                protocol = SL_TagProtocol.SL_TAG_PROTOCOL_IPX256;
                break;
            default:
                protocol = SL_TagProtocol.SL_TAG_PROTOCOL_GEN2;
                break;
        }
        return Collections.singletonList(protocol);
    }
}